﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace GraphicSplit101
{
    public class GrayConvertor
    {
        /// <summary>
        /// GetGrayBytes2D:下标0代表x轴坐标，1代表y轴坐标。默认提取绿色通道像素值。
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static byte[,] GetGrayBytes2D(Bitmap bitmap)
        {
            if (bitmap == null) return null;
            string strPixelFormat=bitmap.PixelFormat.ToString();
            if (strPixelFormat == "Format8bppIndexed")
            {
                return ConvertGrayBytesToDoubleArray(GetGrayBytesFor8bit(bitmap),bitmap.Width,bitmap.Height);
            }
            else if (strPixelFormat == "Format32bppArgb")
            {
                return ConvertGrayBytesToDoubleArray(GetGrayBytesFor32bit(bitmap,2), bitmap.Width, bitmap.Height);
            }
            else
            { 
                //error msg
                return null;
            }
        }
        /// <summary>        
        /// </summary>        
        /// <param name="intMethod">0:r*0.299+g*0.587+b*0.114 1:提取红色通道 2:提取绿色通道 3:提取蓝色通道;</param>
        /// <returns></returns>
        public static byte[,] GetGrayBytes2D(Bitmap bitmap,int intMethod)
        {
            if (bitmap == null) return null;
            string strPixelFormat = bitmap.PixelFormat.ToString();
            if (strPixelFormat == "U8")
            {
                return ConvertGrayBytesToDoubleArray(GetGrayBytesFor8bit(bitmap), bitmap.Width, bitmap.Height);
            }
            else if (strPixelFormat == "U32")
            {
                return ConvertGrayBytesToDoubleArray(GetGrayBytesFor32bit(bitmap,intMethod), bitmap.Width, bitmap.Height);
            }
            else
            {
                //error msg
                return null;
            }
        }
        /// <summary>
        /// GetGrayBytes1D:默认提取绿色通道像素值。
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static byte[] GetGrayBytes1D(Bitmap bitmap)
        {
            if (bitmap == null) return null;
            string strPixelFormat = bitmap.PixelFormat.ToString();
            if (strPixelFormat == "U8")
            {
                return GetGrayBytesFor8bit(bitmap);
            }
            else if (strPixelFormat == "U32")
            {
                return GetGrayBytesFor32bit(bitmap,2);
            }
            else
            {
                //error msg
                return null;
            }
        }
        /// <summary>        
        /// </summary>        
        /// <param name="intMethod">0:r*0.299+g*0.587+b*0.114 1:提取红色通道 2:提取绿色通道 3:提取蓝色通道;</param>
        /// <returns></returns>
        public static byte[] GetGrayBytes1D(Bitmap bitmap,int intMethod)
        {
            if (bitmap == null) return null;
            string strPixelFormat = bitmap.PixelFormat.ToString();
            if (strPixelFormat == "U8")
            {
                return GetGrayBytesFor8bit(bitmap);
            }
            else if (strPixelFormat == "U32")
            {
                return GetGrayBytesFor32bit(bitmap, intMethod);
            }
            else
            {
                //error msg
                return null;
            }
        }
        private static byte[] GetGrayBytesFor8bit(Bitmap bitmap)
        {            
            byte[] grayValues = null;
            try
            {
                if (bitmap != null)
                {
                    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                    System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
                    IntPtr ptr = bmpData.Scan0;
                    int bytes = bitmap.Width * bitmap.Height;
                    grayValues = new byte[bytes];
                    System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
                    bitmap.UnlockBits(bmpData);
                }
                return grayValues;
            }
            catch (Exception ex)
            { 
                Console.WriteLine(string.Format("GetGrayBytesFor8bit:{0}",ex.Message));
                return null;
            }
        }
        private static byte[] GetGrayBytesFor32bit(Bitmap bitmap,int intMethod)
        {
            byte[] rgbValues = null;
            byte[] grayValues = null;
            if (bitmap != null)
            {
                double r = 0, g = 0, b = 0;
                switch (intMethod)
                {
                    case 0:
                        {
                            r = 0.299;
                            g = 0.587;
                            b = 0.114;
                            break;                        
                        }
                    case 1:
                        {
                            r = 1;
                            g = 0;
                            b = 0;
                            break;
                        }
                    case 2:
                        {
                            r = 0;
                            g = 1;
                            b = 0;
                            break;                        
                        }
                    case 3:
                        {
                            r = 0;
                            g = 0;
                            b = 1;
                            break;
                        }
                    default:
                        r = 0;
                        g = 1;
                        b = 0;
                        break;
                }
                try
                {
                    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                    System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
                    IntPtr ptr = bmpData.Scan0;
                    int bytes = bitmap.Width * bitmap.Height;
                    int rgbBytes = bytes * 3;
                    rgbValues = new byte[rgbBytes];
                    grayValues = new byte[bytes];
                    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, rgbBytes);
                    int j = 0;
                    for (int i = 0; i < bytes; i += 3)
                    {
                        double colorTemp = rgbValues[i + 2] * r + rgbValues[i + 1] * g + rgbValues[i] * b;
                        grayValues[j++] = (byte)colorTemp;
                    }
                    bitmap.UnlockBits(bmpData);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("GetGrayBytesFor32bit:{0}", ex.Message));
                }
            }
            return grayValues;
        }
        private static byte[,] ConvertGrayBytesToDoubleArray(byte[] grayBytes, int imageWidth, int imageHeight)
        {
            byte[,] processedGrayBytes = new byte[imageWidth, imageHeight];
            int k = 0;
            for (int j = 0; j < imageHeight; j++)
            {
                for (int i = 0; i < imageWidth; i++)
                {
                    processedGrayBytes[i, j] = grayBytes[k++];
                }
            }
            return processedGrayBytes;
        }
    }
}
